﻿using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;

public class AnimInfoOutput
{

    [MenuItem("Animtion/exportTest")]
    static void export()
    {
        string clipPath = "Assets/AnimExport/Animation/MoveSkill.anim";
        AnimationClip clip = AssetDatabase.LoadAssetAtPath<AnimationClip>(clipPath);
        OutputAnim(clip,clip.frameRate);
    }

    public static void OutputAnim(AnimationClip currentClip,float frameRate)
    {
        if (currentClip == null)
        {
            Debug.LogError("动画名为空");
            return;
        }
        if (!Directory.Exists(AnimConfig.folderPath))
        {
            Directory.CreateDirectory(AnimConfig.folderPath);
        }

        AnimationData animationData = new AnimationData();
        animationData.length = currentClip.length;
        animationData.m_bIsLoop = currentClip.isLooping;
        animationData.m_fDurationTime = currentClip.averageDuration;
        animationData.m_fFrameRate = frameRate;
        animationData.m_sAnimationName = currentClip.name;
        foreach (EditorCurveBinding binding in AnimationUtility.GetCurveBindings(currentClip))
        {
            if (binding.path != AnimConfig.modelRoot)
            {
                //continue;
            }
            if (!binding.propertyName.Contains("m_LocalPosition") && !binding.propertyName.Contains("localEulerAnglesRaw"))
            {
                continue;
            }
            //测试单个曲线
            //if (!binding.propertyName.Contains("m_LocalPosition.x"))
            //{
            //    continue;
            //}
            CurveBinding curveBinding = new CurveBinding();
            curveBinding.averageDuration = currentClip.averageDuration;
            curveBinding.path = binding.path;
            curveBinding.propertyName = binding.propertyName;

            AnimationCurve animationCurve = AnimationUtility.GetEditorCurve(currentClip, binding);
            for (int i = 0; i < animationCurve.keys.Length; i++)
            {
                m_KeyFrame keyFrame = new m_KeyFrame();
                keyFrame.time = animationCurve.keys[i].time;
                keyFrame.value = animationCurve.keys[i].value;
                keyFrame.inTangent = animationCurve.keys[i].inTangent;
                keyFrame.outTangent = animationCurve.keys[i].outTangent;
                keyFrame.inWeight = animationCurve.keys[i].inWeight;
                keyFrame.outWeight = animationCurve.keys[i].outWeight;
                keyFrame.weightedMode = animationCurve.keys[i].weightedMode;

                curveBinding.m_KeyFrames.Add(keyFrame);
            }
            animationData.curveBindings.Add(curveBinding);
        }

        //ConvertAnimCurve(animationData);
        ConvertAnimCurveFinal(animationData);
    }

    static void ConvertAnimCurveFinal(AnimationData animData)
    {
        if (animData == null)
            return;

        if (AnimConfig.debugModel)
            animData.WriteToJson(animData.m_sAnimationName);
        animData.LerpBinding();
        if (AnimConfig.debugModel)
            animData.WriteToJson(animData.m_sAnimationName + "_lerpBinding");

        if (!animData.IsValidValue())
        {
            Debug.Log("没有位移旋转信息：" + animData.m_sAnimationName);
            return;
        }

        AnimTransformData transformData = new AnimTransformData();

        transformData.name = animData.m_sAnimationName;
        transformData.length = animData.length;
        transformData.frameRate = animData.m_fFrameRate;

        foreach (var curve in animData.curveBindings)
        {
            if (curve.propertyName == "m_LocalPosition.x")
            {
                foreach (var keyFrame in curve.finalKeyFrames)
                {
                    ModifyPosition(transformData, keyFrame, animData.m_fFrameRate, "x");
                }
            }
            if (curve.propertyName == "m_LocalPosition.y")
            {
                foreach (var keyFrame in curve.finalKeyFrames)
                {
                    ModifyPosition(transformData, keyFrame, animData.m_fFrameRate, "y");
                }
            }
            if (curve.propertyName == "m_LocalPosition.z")
            {
                foreach (var keyFrame in curve.finalKeyFrames)
                {
                    ModifyPosition(transformData, keyFrame, animData.m_fFrameRate, "z");
                }
            }

            if (curve.propertyName == "localEulerAnglesRaw.x")
            {
                foreach (var keyFrame in curve.finalKeyFrames)
                {
                    ModifyRotation(transformData, keyFrame, animData.m_fFrameRate, "x");
                }
            }
            if (curve.propertyName == "localEulerAnglesRaw.y")
            {
                foreach (var keyFrame in curve.finalKeyFrames)
                {
                    ModifyRotation(transformData, keyFrame, animData.m_fFrameRate, "y");
                }
            }
            if (curve.propertyName == "localEulerAnglesRaw.z")
            {
                foreach (var keyFrame in curve.finalKeyFrames)
                {
                    ModifyRotation(transformData, keyFrame, animData.m_fFrameRate, "z");
                }
            }
        }
        transformData.MergeFrameData();
        transformData.WriteToJson();
    }

    //线性插值，弃用
    static void ConvertAnimCurve(AnimationData animData)
    {
        if (animData == null)
        {
            return;
        }

        AnimTransformData transformData = new AnimTransformData();

        transformData.name = animData.m_sAnimationName;
        transformData.length = animData.length;
        transformData.frameRate = animData.m_fFrameRate;

        foreach (var curve in animData.curveBindings)
        {
            if (curve.propertyName == "m_LocalPosition.x")
            {
                foreach (var keyFrame in curve.m_KeyFrames)
                {
                    ModifyPosition(transformData, keyFrame, animData.m_fFrameRate, "x");
                }
            }
            if (curve.propertyName == "m_LocalPosition.y")
            {
                foreach (var keyFrame in curve.m_KeyFrames)
                {
                    ModifyPosition(transformData, keyFrame, animData.m_fFrameRate, "y");
                }
            }
            if (curve.propertyName == "m_LocalPosition.z")
            {
                foreach (var keyFrame in curve.m_KeyFrames)
                {
                    ModifyPosition(transformData, keyFrame, animData.m_fFrameRate, "z");
                }
            }

            if (curve.propertyName == "localEulerAnglesRaw.x")
            {
                foreach (var keyFrame in curve.m_KeyFrames)
                {
                    ModifyRotation(transformData, keyFrame, animData.m_fFrameRate, "x");
                }
            }
            if (curve.propertyName == "localEulerAnglesRaw.y")
            {
                foreach (var keyFrame in curve.m_KeyFrames)
                {
                    ModifyRotation(transformData, keyFrame, animData.m_fFrameRate, "y");
                }
            }
            if (curve.propertyName == "localEulerAnglesRaw.z")
            {
                foreach (var keyFrame in curve.m_KeyFrames)
                {
                    ModifyRotation(transformData, keyFrame, animData.m_fFrameRate, "z");
                }
            }
        }

        transformData.lerpFrameData();
        string json = JsonUtility.ToJson(transformData, true);
        string path = AnimConfig.folderPath + "/" + transformData.name + "_trans.json";
        File.WriteAllText(path, json);
    }

    static void ModifyPosition(AnimTransformData transformData, m_KeyFrame keyFrame, float frameRate, string axis)
    {
        //计算出帧数
        int frame = Mathf.RoundToInt(keyFrame.time * frameRate);
        PositionData transData = transformData.GetPositionDataByFrame(frame);
        if (transData == null)
        {
            transData = new PositionData(keyFrame.time, frame);
            transformData.AddPositionData(transData);
        }
        if (axis == "x")
            transData.position.x = keyFrame.value;
        else if (axis == "y")
            transData.position.y = keyFrame.value;
        else if (axis == "z")
            transData.position.z = keyFrame.value;
    }
    static void ModifyRotation(AnimTransformData transformData, m_KeyFrame keyFrame, float frameRate, string axis)
    {
        //计算出帧数
        int frame = Mathf.RoundToInt(keyFrame.time * frameRate);
        RotationData transData = transformData.GetRotationDataByFrame(frame);
        if (transData == null)
        {
            transData = new RotationData(keyFrame.time, frame);
            transformData.AddRotationData(transData);
        }
        if (axis == "x")
            transData.rotation.x = keyFrame.value;
        else if (axis == "y")
            transData.rotation.y = keyFrame.value;
        else if (axis == "z")
            transData.rotation.z = keyFrame.value;
    }
}